package main;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

public class Simulator extends JPanel implements MouseListener, MouseMotionListener {

    // Create robot starting in top corner of environment, with velocity of 1
    private Robot robot = new Robot(300, 300, 1, 1);
    
    public static PointOfInterest poi = new PointOfInterest();
    public static PointOfInterest2 poi2 = new PointOfInterest2();
    
    public static boolean editing = false;
    public static int closest = -1;
    public static Point old_closest = null;

    // Timer updates animation one step
    public static Timer timer;
    public static Timer msg;

    // Arrays to hold sensor readings
    public double[] sonarSensorReadings;
    public double[] infraRedSensorReadings;

    public static JLabel help_label;
    public static JLabel message_label;
    
    // Constructor
    public Simulator() {
        setPreferredSize(new Dimension(600, 600));
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        int interval = 35;
        
                
        help_label = new JLabel("", new ImageIcon("help.png"), JLabel.LEFT);
        help_label.setLocation(0, 0);
        Dimension size = help_label.getPreferredSize();
        help_label.setBounds(5,5, size.width, size.height);
        add(help_label);
        this.setLayout(null);
        help_label.addMouseListener(this);

        message_label = new JLabel("");
        message_label.setFont(Fonts.default_font(22));        
        size = message_label.getPreferredSize();
        message_label.setBounds(300-size.width/2,300-size.height/2, size.width, size.height);
        add(message_label);
        //message_label.setVisible(false);
        
        msg = new Timer(1500, new MessageAction());
        
        timer = new Timer(interval, new TimerAction());
       // sonarSensorReadings = robot.getSonarReadings();
       // infraRedSensorReadings = robot.getInfraRedReadings();
        addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    // Animation/movement control
    public static void setAnimation(boolean turnOnOff) {
        if (turnOnOff) {
            timer.start();  // start animation by starting the timer.
        } else {
            timer.stop();   // stop timer
        }
    }

    // Public target location setting method
    public void setTarget(int x, int y) {
        robot.setWayPoint(x,y);
        
    }

    // Paint component for drawing the environment
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // Draw border
        robot.draw(g); // Draw the robot
        SimulatorPanel.sensorPanel.repaint();
    }
    
    // ActionListener for committing actions as the timer ticks
    class TimerAction implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            robot.setBounds(getWidth(), getHeight());
            robot.move2(); // Update robot position
            
          //  sonarSensorReadings = robot.getSonarReadings(); // Update sensor readings
          //  infraRedSensorReadings = robot.getInfraRedReadings(); // Update IR readings
            repaint();      // Repaint indirectly calls paintComponent.
        }
    }

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		//System.out.print("click : " + arg0.getPoint().x + " " + arg0.getPoint().y +"\n");
		//robot.setWayPoint(new Point(arg0.getPoint()));
		//repaint();		
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		
		if (timer.isRunning()) {
			this.setAnimation(false);
			return;
		}
		
		Point p = new Point(arg0.getPoint());
		if (arg0.getSource().equals(help_label)) {
			UserInterface.setContentPane(UserInterface.demo);
			return;
		}
		
		if (poi.place.distanceFromPoint(p) < 25) {
			UserInterface.simulatorPanel.infoPanel.removeAll();
			UserInterface.simulatorPanel.infoPanel.add(poi.tooltip);
			UserInterface.simulatorPanel.infoPanel.doLayout();
			UserInterface.simulatorPanel.repaint();
			repaint();
			// do sth
			return;
		}
		
		if (poi2.place.distanceFromPoint(p) < 25) {
			UserInterface.simulatorPanel.infoPanel.removeAll();
			UserInterface.simulatorPanel.infoPanel.add(poi2.tooltip);
			UserInterface.simulatorPanel.infoPanel.doLayout();
			UserInterface.simulatorPanel.repaint();
			repaint();
			// do sth
			return;
		}
		
		
		
		
		
		closest = Robot.getClosestWaypoint(p);
		
		if (closest != -1) {
			editing = true;
			this.old_closest = Robot.waypoints.get(closest);
			Robot.waypoints.set(closest, p);
		} else {		
			Robot.temp = p;
		}
		repaint();
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		if (timer.isRunning()) {
			return;
		}
		
		Point p = new Point(arg0.getPoint());
		
		if (editing) {			
						
			if (p.x >= 600 || p.y >= 600 || p.x <= 0 || p.y <= 0) {				
				while (Robot.waypoints.size() > closest) {
					Robot.waypoints.remove(closest);
					Simulator.showBadMessage("Waypoint removed!");
					if (closest == 0) {
						Robot.destination = Robot.position;						
					}
				}				
			} else if (p.x >= 558 || p.y >= 558 || p.x <= 40 || p.y <= 40) {
				Robot.waypoints.set(closest, old_closest);
				if (closest == 0) {
					Robot.destination = old_closest;
					showBadMessage("Too close to boundary!");
				}
			} else {
				showGoodMessage("Waypoint moved!");
			}
	    		
			
			
			editing = false;
			closest = -1;
			repaint();
			return;
		}
		
		if (Robot.temp != null) {
			robot.setWayPoint(p);
			Robot.temp = null;
			repaint();
		}
	}
	
	public static void showGoodMessage(String msg) {
		message_label.setText(msg);
		Dimension size = message_label.getPreferredSize();
        message_label.setBounds(300-size.width/2,300-size.height/2, size.width, size.height);
		message_label.setVisible(true);
		
		message_label.setForeground(new Color(0, 128, 0));
		
		Simulator.msg.stop();
		Simulator.msg.start();
	}
	
	public static void showBadMessage(String msg) {
		message_label.setText(msg);
		Dimension size = message_label.getPreferredSize();
        message_label.setBounds(300-size.width/2,300-size.height/2, size.width, size.height);
		message_label.setVisible(true);
		
		message_label.setForeground(new Color(128, 0, 0));
		
		Simulator.msg.stop();
		Simulator.msg.start();
	}
	
	// ActionListener for committing actions as the timer ticks
    class MessageAction implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            message_label.setVisible(false);
            msg.stop();
        }
    }

	@Override
	public void mouseDragged(MouseEvent arg0) {
		if (timer.isRunning()) {
			return;
		}		
		
		Point p = new Point(arg0.getPoint());
		
		if (editing) {
			if (closest == 0) {
				Robot.destination = p;
			}
			
			Robot.waypoints.set(closest, p);
			repaint();
			return;
		}
				
		Robot.temp = p;
		repaint();
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
	}
}
